home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / turbo.c < prev    next >
C/C++ Source or Header  |  2000-01-25  |  19KB  |  687 lines

  1. /*************************************************************************
  2.  
  3.      Turbo - Sega - 1981
  4.  
  5.      Video Hardware
  6.  
  7. *************************************************************************/
  8.  
  9. #ifndef DRAW_CORE_INCLUDE
  10.  
  11. #include "driver.h"
  12. #include "vidhrdw/generic.h"
  13.  
  14. /* constants */
  15. #define VIEW_WIDTH                    (32*8)
  16. #define VIEW_HEIGHT                    (28*8)
  17.  
  18. /* external definitions */
  19. UINT8 *turbo_sprite_position;
  20. UINT8 turbo_collision;
  21.  
  22. /* from machine */
  23. extern UINT8 turbo_opa, turbo_opb, turbo_opc;
  24. extern UINT8 turbo_ipa, turbo_ipb, turbo_ipc;
  25. extern UINT8 turbo_fbpla, turbo_fbcol;
  26. extern UINT8 turbo_segment_data[32];
  27. extern UINT8 turbo_speed;
  28.  
  29. /* internal data */
  30. static UINT8 *sprite_gfxdata, *sprite_priority;
  31. static UINT8 *road_gfxdata, *road_palette, *road_enable_collide;
  32. static UINT8 *back_gfxdata, *back_palette;
  33. static UINT8 *overall_priority, *collision_map;
  34.  
  35. /* sprite tracking */
  36. struct sprite_params_data
  37. {
  38.     UINT32 *base;
  39.     int offset, rowbytes;
  40.     int yscale, miny, maxy;
  41.     int xscale, xoffs;
  42. };
  43. static struct sprite_params_data sprite_params[16];
  44. static UINT32 *sprite_expanded_data;
  45.  
  46. /* orientation */
  47. static const struct rectangle game_clip = { 0, VIEW_WIDTH - 1, 64, 64 + VIEW_HEIGHT - 1 };
  48. static struct rectangle adjusted_clip;
  49. static int startx, starty, deltax, deltay;
  50.  
  51. /* misc other stuff */
  52. static UINT16 *back_expanded_data;
  53. static UINT16 *road_expanded_palette;
  54. static UINT8 drew_frame;
  55.  
  56. /* prototypes */
  57. static void draw_everything_core_8(struct osd_bitmap *bitmap);
  58. static void draw_everything_core_16(struct osd_bitmap *bitmap);
  59. static void draw_minimal(struct osd_bitmap *bitmap);
  60.  
  61.  
  62. /***************************************************************************
  63.  
  64.   Convert the color PROMs into a more useable format.
  65.  
  66. ***************************************************************************/
  67.  
  68. void turbo_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable, const unsigned char *color_prom)
  69. {
  70.     int i;
  71.  
  72.     for (i = 0; i < 512; i++, color_prom++)
  73.     {
  74.         int bit0, bit1, bit2;
  75.  
  76.         /* bits 4,5,6 of the index are inverted before being used as addresses */
  77.         /* to save ourselves lots of trouble, we will undo the inversion when */
  78.         /* generating the palette */
  79.         int adjusted_index = i ^ 0x70;
  80.  
  81.         /* red component */
  82.         bit0 = (*color_prom >> 0) & 1;
  83.         bit1 = (*color_prom >> 1) & 1;
  84.         bit2 = (*color_prom >> 2) & 1;
  85.         palette[adjusted_index * 3 + 0] = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  86.  
  87.         /* green component */
  88.         bit0 = (*color_prom >> 3) & 1;
  89.         bit1 = (*color_prom >> 4) & 1;
  90.         bit2 = (*color_prom >> 5) & 1;
  91.         palette[adjusted_index * 3 + 1] = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  92.  
  93.         /* blue component */
  94.         bit0 = 0;
  95.         bit1 = (*color_prom >> 6) & 1;
  96.         bit2 = (*color_prom >> 7) & 1;
  97.         palette[adjusted_index * 3 + 2] = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  98.     }
  99.  
  100.     /* LED segments colors: black and red */
  101.     palette[512 * 3 + 0] = 0x00;
  102.     palette[512 * 3 + 1] = 0x00;
  103.     palette[512 * 3 + 2] = 0x00;
  104.     palette[513 * 3 + 0] = 0xff;
  105.     palette[513 * 3 + 1] = 0x00;
  106.     palette[513 * 3 + 2] = 0x00;
  107.     /* Tachometer colors: Led colors + yellow and green */
  108.     palette[514 * 3 + 0] = 0x00;
  109.     palette[514 * 3 + 1] = 0x00;
  110.     palette[514 * 3 + 2] = 0x00;
  111.     palette[515 * 3 + 0] = 0xff;
  112.     palette[515 * 3 + 1] = 0xff;
  113.     palette[515 * 3 + 2] = 0x00;
  114.     palette[516 * 3 + 0] = 0x00;
  115.     palette[516 * 3 + 1] = 0x00;
  116.     palette[516 * 3 + 2] = 0x00;
  117.     palette[517 * 3 + 0] = 0x00;
  118.     palette[517 * 3 + 1] = 0xff;
  119.     palette[517 * 3 + 2] = 0x00;
  120. }
  121.  
  122.  
  123. /***************************************************************************
  124.  
  125.   Video startup/shutdown
  126.  
  127. ***************************************************************************/
  128.  
  129. int turbo_vh_start(void)
  130. {
  131.     int i, j, sprite_length, sprite_bank_size, back_length;
  132.     UINT32 sprite_expand[16];
  133.     UINT32 *dst;
  134.     UINT16 *bdst;
  135.     UINT8 *src;
  136.  
  137.     /* allocate the expanded sprite data */
  138.     sprite_length = memory_region_length(REGION_GFX1);
  139.     sprite_bank_size = sprite_length / 8;
  140.     sprite_expanded_data = malloc(sprite_length * 2 * sizeof(UINT32));
  141.     if (!sprite_expanded_data)
  142.         return 1;
  143.  
  144.     /* allocate the expanded background data */
  145.     back_length = memory_region_length(REGION_GFX3);
  146.     back_expanded_data = malloc(back_length);
  147.     if (!back_expanded_data)
  148.     {
  149.         free(sprite_expanded_data);
  150.         return 1;
  151.     }
  152.  
  153.     /* allocate the expanded road palette */
  154.     road_expanded_palette = malloc(0x40 * sizeof(UINT16));
  155.     if (!road_expanded_palette)
  156.     {
  157.         free(back_expanded_data);
  158.         free(sprite_expanded_data);
  159.         return 1;
  160.     }
  161.  
  162.     /* determine ROM/PROM addresses */
  163.     sprite_gfxdata = memory_region(REGION_GFX1);
  164.     sprite_priority = memory_region(REGION_PROMS) + 0x0200;
  165.  
  166.     road_gfxdata = memory_region(REGION_GFX2);
  167.     road_palette = memory_region(REGION_PROMS) + 0x0b00;
  168.     road_enable_collide = memory_region(REGION_PROMS) + 0x0b40;
  169.  
  170.     back_gfxdata = memory_region(REGION_GFX3);
  171.     back_palette = memory_region(REGION_PROMS) + 0x0a00;
  172.  
  173.     overall_priority = memory_region(REGION_PROMS) + 0x0600;
  174.     collision_map = memory_region(REGION_PROMS) + 0x0b60;
  175.  
  176.     /* compute the sprite expansion array */
  177.     for (i = 0; i < 16; i++)
  178.     {
  179.         UINT32 value = 0;
  180.         if (i & 1) value |= 0x00000001;
  181.         if (i & 2) value |= 0x00000100;
  182.         if (i & 4) value |= 0x00010000;
  183.         if (i & 8) value |= 0x01000000;
  184.  
  185.         /* special value for the end-of-row */
  186.         if ((i & 0x0c) == 0x04) value = 0x12345678;
  187.  
  188.         sprite_expand[i] = value;
  189.     }
  190.  
  191.     /* expand the sprite ROMs */
  192.     src = sprite_gfxdata;
  193.     dst = sprite_expanded_data;
  194.     for (i = 0; i < 8; i++)
  195.     {
  196.         /* expand this bank */
  197.         for (j = 0; j < sprite_bank_size; j++)
  198.         {
  199.             *dst++ = sprite_expand[*src >> 4];
  200.             *dst++ = sprite_expand[*src++ & 15];
  201.         }
  202.  
  203.         /* shift for the next bank */
  204.         for (j = 0; j < 16; j++)
  205.             if (sprite_expand[j] != 0x12345678) sprite_expand[j] <<= 1;
  206.     }
  207.  
  208.     /* expand the background ROMs */
  209.     src = back_gfxdata;
  210.     bdst = back_expanded_data;
  211.     for (i = 0; i < back_length / 2; i++, src++)
  212.     {
  213.         int bits1 = src[0];
  214.         int bits2 = src[back_length / 2];
  215.         int newbits = 0;
  216.  
  217.         for (j = 0; j < 8; j++)
  218.         {
  219.             newbits |= ((bits1 >> (j ^ 7)) & 1) << (j * 2);
  220.             newbits |= ((bits2 >> (j ^ 7)) & 1) << (j * 2 + 1);
  221.         }
  222.         *bdst++ = newbits;
  223.     }
  224.  
  225.     /* expand the road palette */
  226.     src = road_palette;
  227.     bdst = road_expanded_palette;
  228.     for (i = 0; i < 0x20; i++, src++)
  229.         *bdst++ = src[0] | (src[0x20] << 8);
  230.  
  231.     /* set the default drawing parameters */
  232.     startx = game_clip.min_x;
  233.     starty = game_clip.min_y;
  234.     deltax = deltay = 1;
  235.     adjusted_clip = game_clip;
  236.  
  237.     /* adjust our parameters for the specified orientation */
  238.     if (Machine->orientation)
  239.     {
  240.         int temp;
  241.  
  242.         if (Machine->orientation & ORIENTATION_SWAP_XY)
  243.         {
  244.             temp = startx; startx = starty; starty = temp;
  245.             temp = adjusted_clip.min_x; adjusted_clip.min_x = adjusted_clip.min_y; adjusted_clip.min_y = temp;
  246.             temp = adjusted_clip.max_x; adjusted_clip.max_x = adjusted_clip.max_y; adjusted_clip.max_y = temp;
  247.         }
  248.         if (Machine->orientation & ORIENTATION_FLIP_X)
  249.         {
  250.             startx = adjusted_clip.max_x;
  251.             if (!(Machine->orientation & ORIENTATION_SWAP_XY)) deltax = -deltax;
  252.             else deltay = -deltay;
  253.         }
  254.         if (Machine->orientation & ORIENTATION_FLIP_Y)
  255.         {
  256.             starty = adjusted_clip.max_y;
  257.             if (!(Machine->orientation & ORIENTATION_SWAP_XY)) deltay = -deltay;
  258.             else deltax = -deltax;
  259.         }
  260.     }
  261.  
  262.     /* other stuff */
  263.     drew_frame = 0;
  264.  
  265.     /* return success */
  266.     return 0;
  267. }
  268.  
  269.  
  270. void turbo_vh_stop(void)
  271. {
  272.     free(sprite_expanded_data);
  273.     free(back_expanded_data);
  274.     free(road_expanded_palette);
  275. }
  276.  
  277.  
  278. /***************************************************************************
  279.  
  280.   Sprite information
  281.  
  282. ***************************************************************************/
  283.  
  284. static void update_sprite_info(void)
  285. {
  286.     struct sprite_params_data *data = sprite_params;
  287.     int i;
  288.  
  289.     /* first loop over all sprites and update those whose scanlines intersect ours */
  290.     for (i = 0; i < 16; i++, data++)
  291.     {
  292.         UINT8 *sprite_base = spriteram + 16 * i;
  293.  
  294.         /* snarf all the data */
  295.         data->base = sprite_expanded_data + (i & 7) * 0x8000;
  296.         data->offset = (sprite_base[6] + 256 * sprite_base[7]) & 0x7fff;
  297.         data->rowbytes = (INT16)(sprite_base[4] + 256 * sprite_base[5]);
  298.         data->miny = sprite_base[0];
  299.         data->maxy = sprite_base[1];
  300.         data->xscale = ((5 * 256 - 4 * sprite_base[2]) << 16) / (5 * 256);
  301.         data->yscale = (4 << 16) / (sprite_base[3] + 4);
  302.         data->xoffs = -1;
  303.     }
  304.  
  305.     /* now find the X positions */
  306.     for (i = 0; i < 0x200; i++)
  307.     {
  308.         int value = turbo_sprite_position[i];
  309.         if (value)
  310.         {
  311.             int base = (i & 0x100) >> 5;
  312.             int which;
  313.             for (which = 0; which < 8; which++)
  314.                 if (value & (1 << which))
  315.                     sprite_params[base + which].xoffs = i & 0xff;
  316.         }
  317.     }
  318. }
  319.  
  320.  
  321. /***************************************************************************
  322.  
  323.   Internal draw routines
  324.  
  325. ***************************************************************************/
  326.  
  327. static void draw_one_sprite(const struct sprite_params_data *data, UINT32 *dest, int xclip, int scanline)
  328. {
  329.     int xstep = data->xscale;
  330.     int xoffs = data->xoffs;
  331.     int xcurr, offset;
  332.     UINT32 *src;
  333.  
  334.     /* xoffs of -1 means don't draw */
  335.     if (xoffs == -1) return;
  336.  
  337.     /* clip to the road */
  338.     xcurr = 0;
  339.     if (xoffs < xclip)
  340.     {
  341.         /* the pixel clock starts on xoffs regardless of clipping; take this into account */
  342.         xcurr = ((xclip - xoffs) * xstep) & 0xffff;
  343.         xoffs = xclip;
  344.     }
  345.  
  346.     /* compute the current data offset */
  347.     scanline = ((scanline - data->miny) * data->yscale) >> 16;
  348.     offset = data->offset + (scanline + 1) * data->rowbytes;
  349.  
  350.     /* determine the bitmap location */
  351.     src = &data->base[offset & 0x7fff];
  352.  
  353.     /* loop over columns */
  354.     while (xoffs < VIEW_WIDTH)
  355.     {
  356.         UINT32 srcval = src[xcurr >> 16];
  357.  
  358.         /* stop on the end-of-row signal */
  359.         if (srcval == 0x12345678) break;
  360.         dest[xoffs++] |= srcval;
  361.         xcurr += xstep;
  362.     }
  363. }
  364.  
  365.  
  366. static void draw_road_sprites(UINT32 *dest, int scanline)
  367. {
  368.     static const struct sprite_params_data *param_list[6] =
  369.     {
  370.         &sprite_params[0], &sprite_params[8],
  371.         &sprite_params[1], &sprite_params[9],
  372.         &sprite_params[2], &sprite_params[10]
  373.     };
  374.     int i;
  375.  
  376.     /* loop over the road sprites */
  377.     for (i = 0; i < 6; i++)
  378.     {
  379.         const struct sprite_params_data *data = param_list[i];
  380.  
  381.         /* if the sprite intersects this scanline, draw it */
  382.         if (scanline >= data->miny && scanline < data->maxy)
  383.             draw_one_sprite(data, dest, 0, scanline);
  384.     }
  385. }
  386.  
  387.  
  388. static void draw_offroad_sprites(UINT32 *dest, int road_column, int scanline)
  389. {
  390.     static const struct sprite_params_data *param_list[10] =
  391.     {
  392.         &sprite_params[3], &sprite_params[11],
  393.         &sprite_params[4], &sprite_params[12],
  394.         &sprite_params[5], &sprite_params[13],
  395.         &sprite_params[6], &sprite_params[14],
  396.         &sprite_params[7], &sprite_params[15]
  397.     };
  398.     int i;
  399.  
  400.     /* loop over the offroad sprites */
  401.     for (i = 0; i < 10; i++)
  402.     {
  403.         const struct sprite_params_data *data = param_list[i];
  404.  
  405.         /* if the sprite intersects this scanline, draw it */
  406.         if (scanline >= data->miny && scanline < data->maxy)
  407.             draw_one_sprite(data, dest, road_column, scanline);
  408.     }
  409. }
  410.  
  411.  
  412. static void draw_scores(struct osd_bitmap *bitmap)
  413. {
  414.     struct rectangle clip;
  415.     int offs, x, y;
  416.  
  417.     /* current score */
  418.     offs = 31;
  419.     for (y = 0; y < 5; y++, offs--)
  420.         drawgfx(bitmap, Machine->gfx[0],
  421.                 turbo_segment_data[offs],
  422.                 0,
  423.                 0, 0,
  424.                 14*8, (2 + y) * 8,
  425.                 &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  426.  
  427.     /* high scores */
  428.     for (x = 0; x < 5; x++)
  429.     {
  430.         offs = 6 + x * 5;
  431.         for (y = 0; y < 5; y++, offs--)
  432.             drawgfx(bitmap, Machine->gfx[0],
  433.                     turbo_segment_data[offs],
  434.                     0,
  435.                     0, 0,
  436.                     (20 + 2 * x) * 8, (2 + y) * 8,
  437.                     &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  438.     }
  439.  
  440.     /* tachometer */
  441.     clip = Machine->drv->visible_area;
  442.     clip.min_x = 5*8;
  443.     clip.max_x = clip.min_x + 1;
  444.     for (y = 0; y < 22; y++)
  445.     {
  446.         static UINT8 led_color[] = { 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0 };
  447.         int code = ((y / 2) <= turbo_speed) ? 0 : 1;
  448.  
  449.         drawgfx(bitmap, Machine->gfx[1],
  450.                 code,
  451.                 led_color[y / 2],
  452.                 0,0,
  453.                 5*8, y*2+8,
  454.                 &clip, TRANSPARENCY_NONE, 0);
  455.         if (y % 3 == 2)
  456.             clip.max_x++;
  457.     }
  458.  
  459.     /* shifter status */
  460.     if (readinputport(0) & 0x04)
  461.     {
  462.         drawgfx(bitmap, Machine->gfx[2], 'H', 0, 0,0, 2*8,3*8, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  463.         drawgfx(bitmap, Machine->gfx[2], 'I', 0, 0,0, 2*8,4*8, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  464.     }
  465.     else
  466.     {
  467.         drawgfx(bitmap, Machine->gfx[2], 'L', 0, 0,0, 2*8,3*8, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  468.         drawgfx(bitmap, Machine->gfx[2], 'O', 0, 0,0, 2*8,4*8, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  469.     }
  470. }
  471.  
  472.  
  473.  
  474. /***************************************************************************
  475.  
  476.   Master refresh routine
  477.  
  478. ***************************************************************************/
  479.  
  480. void turbo_vh_eof(void)
  481. {
  482.     /* only do collision checking if we didn't draw */
  483.     if (!drew_frame)
  484.     {
  485.         update_sprite_info();
  486.         draw_minimal(Machine->scrbitmap);
  487.     }
  488.     drew_frame = 0;
  489. }
  490.  
  491. void turbo_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  492. {
  493.     /* update the sprite data */
  494.     update_sprite_info();
  495.  
  496.     /* perform the actual drawing */
  497.     if (bitmap->depth == 8)
  498.         draw_everything_core_8(bitmap);
  499.     else
  500.         draw_everything_core_16(bitmap);
  501.  
  502.     /* draw the LEDs for the scores */
  503.     draw_scores(bitmap);
  504.  
  505.     /* indicate that we drew this frame, so that the eof callback doesn't bother doing anything */
  506.     drew_frame = 1;
  507. }
  508.  
  509.  
  510. /***************************************************************************
  511.  
  512.   Road drawing generators
  513.  
  514. ***************************************************************************/
  515.  
  516. #define DRAW_CORE_INCLUDE
  517.  
  518. #define FULL_DRAW    1
  519.  
  520. #define DRAW_FUNC    draw_everything_core_8
  521. #define TYPE        UINT8
  522. #include "turbo.c"
  523. #undef TYPE
  524. #undef DRAW_FUNC
  525.  
  526. #define DRAW_FUNC    draw_everything_core_16
  527. #define TYPE        UINT16
  528. #include "turbo.c"
  529. #undef TYPE
  530. #undef DRAW_FUNC
  531.  
  532. #undef FULL_DRAW
  533. #define FULL_DRAW    0
  534.  
  535. #define DRAW_FUNC    draw_minimal
  536. #define TYPE        UINT8
  537. #include "turbo.c"
  538. #undef TYPE
  539. #undef DRAW_FUNC
  540.  
  541. #undef FULL_DRAW
  542.  
  543. #else
  544.  
  545. /***************************************************************************
  546.  
  547.   Road drawing routine
  548.  
  549. ***************************************************************************/
  550.  
  551. static void DRAW_FUNC(struct osd_bitmap *bitmap)
  552. {
  553.     TYPE *base = &((TYPE *)bitmap->line[starty])[startx];
  554.     UINT32 sprite_buffer[VIEW_WIDTH + 256];
  555.  
  556.     UINT8 *overall_priority_base = &overall_priority[(turbo_fbpla & 8) << 6];
  557.     UINT8 *sprite_priority_base = &sprite_priority[(turbo_fbpla & 7) << 7];
  558.     UINT8 *road_gfxdata_base = &road_gfxdata[(turbo_opc << 5) & 0x7e0];
  559.     UINT16 *road_palette_base = &road_expanded_palette[(turbo_fbcol & 1) << 4];
  560.  
  561.     int dx = deltax, dy = deltay, rowsize = (bitmap->line[1] - bitmap->line[0]) * 8 / bitmap->depth;
  562.     UINT16 *colortable;
  563.     int x, y, i;
  564.  
  565.     /* expand the appropriate delta */
  566.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  567.         dx *= rowsize;
  568.     else
  569.         dy *= rowsize;
  570.  
  571.     /* determine the color offset */
  572.     colortable = &Machine->pens[(turbo_fbcol & 6) << 6];
  573.  
  574.     /* loop over rows */
  575.     for (y = 4; y < VIEW_HEIGHT - 4; y++, base += dy)
  576.     {
  577.         int sel, coch, babit, slipar_acciar, area, area1, area2, area3, area4, area5, road = 0;
  578.         UINT32 *sprite_data = sprite_buffer;
  579.         TYPE *dest = base;
  580.  
  581.         /* compute the Y sum between opa and the current scanline (p. 141) */
  582.         int va = (y + turbo_opa) & 0xff;
  583.  
  584.         /* the upper bit of OPC inverts the road */
  585.         if (!(turbo_opc & 0x80)) va ^= 0xff;
  586.  
  587.         /* clear the sprite buffer and draw the road sprites */
  588.         memset(sprite_buffer, 0, VIEW_WIDTH * sizeof(UINT32));
  589.         draw_road_sprites(sprite_buffer, y);
  590.  
  591.         /* loop over 8-pixel chunks */
  592.         dest += dx * 8;
  593.         sprite_data += 8;
  594.         for (x = 8; x < VIEW_WIDTH; x += 8)
  595.         {
  596.             int area5_buffer = road_gfxdata_base[0x4000 + (x >> 3)];
  597.             UINT8 back_data = videoram[(y / 8) * 32 + (x / 8) - 33];
  598.             UINT16 backbits_buffer = back_expanded_data[(back_data << 3) | (y & 7)];
  599.  
  600.             /* loop over columns */
  601.             for (i = 0; i < 8; i++, dest += dx)
  602.             {
  603.                 UINT32 sprite = *sprite_data++;
  604.  
  605.                 /* compute the X sum between opb and the current column; only the carry matters (p. 141) */
  606.                 int carry = (x + i + turbo_opb) >> 8;
  607.  
  608.                 /* the carry selects which inputs to use (p. 141) */
  609.                 if (carry)
  610.                 {
  611.                     sel     = turbo_ipb;
  612.                     coch = turbo_ipc >> 4;
  613.                 }
  614.                 else
  615.                 {
  616.                     sel     = turbo_ipa;
  617.                     coch = turbo_ipc & 15;
  618.                 }
  619.  
  620.                 /* at this point we also compute area5 (p. 141) */
  621.                 area5 = (area5_buffer >> 3) & 0x10;
  622.                 area5_buffer <<= 1;
  623.  
  624.                 /* now look up the rest of the road bits (p. 142) */
  625.                 area1 = road_gfxdata[0x0000 | ((sel & 15) << 8) | va];
  626.                 area1 = ((area1 + x + i) >> 8) & 0x01;
  627.                 area2 = road_gfxdata[0x1000 | ((sel & 15) << 8) | va];
  628.                 area2 = ((area2 + x + i) >> 7) & 0x02;
  629.                 area3 = road_gfxdata[0x2000 | ((sel >> 4) << 8) | va];
  630.                 area3 = ((area3 + x + i) >> 6) & 0x04;
  631.                 area4 = road_gfxdata[0x3000 | ((sel >> 4) << 8) | va];
  632.                 area4 = ((area4 + x + i) >> 5) & 0x08;
  633.  
  634.                 /* compute the final area value and look it up in IC18/PR1115 (p. 144) */
  635.                 area = area5 | area4 | area3 | area2 | area1;
  636.                 babit = road_enable_collide[area] & 0x07;
  637.  
  638.                 /* note: SLIPAR is 0 on the road surface only */
  639.                 /*         ACCIAR is 0 on the road surface and the striped edges only */
  640.                 slipar_acciar = road_enable_collide[area] & 0x30;
  641.                 if (!road && (slipar_acciar & 0x20))
  642.                 {
  643.                     road = 1;
  644.                     draw_offroad_sprites(sprite_buffer, x + i + 2, y);
  645.                 }
  646.  
  647.                 /* perform collision detection here */
  648.                 turbo_collision |= collision_map[((sprite >> 24) & 7) | (slipar_acciar >> 1)];
  649.  
  650.                 /* we only need to continue if we're actually drawing */
  651.                 if (FULL_DRAW)
  652.                 {
  653.                     int bacol, red, grn, blu, priority, backbits, mx;
  654.  
  655.                     /* also use the coch value to look up color info in IC13/PR1114 and IC21/PR1117 (p. 144) */
  656.                     bacol = road_palette_base[coch & 15];
  657.  
  658.                     /* at this point, do the character lookup */
  659.                     backbits = backbits_buffer & 3;
  660.                     backbits_buffer >>= 2;
  661.                     backbits = back_palette[backbits | (back_data & 0xfc)];
  662.  
  663.                     /* look up the sprite priority in IC11/PR1122 */
  664.                     priority = sprite_priority_base[sprite >> 25];
  665.  
  666.                     /* use that to look up the overall priority in IC12/PR1123 */
  667.                     mx = overall_priority_base[(priority & 7) | ((sprite >> 21) & 8) | ((back_data >> 3) & 0x10) | ((backbits << 2) & 0x20) | (babit << 6)];
  668.  
  669.                     /* the input colors consist of a mix of sprite, road and 1's & 0's */
  670.                     red = 0x040000 | ((bacol & 0x001f) << 13) | ((backbits & 1) << 12) | ((sprite <<  4) & 0x0ff0);
  671.                     grn = 0x080000 | ((bacol & 0x03e0) <<  9) | ((backbits & 2) << 12) | ((sprite >>  3) & 0x1fe0);
  672.                     blu = 0x100000 | ((bacol & 0x7c00) <<  5) | ((backbits & 4) << 12) | ((sprite >> 10) & 0x3fc0);
  673.  
  674.                     /* we then go through a muxer; normally these values are inverted, but */
  675.                     /* we've already taken care of that when we generated the palette */
  676.                     red = (red >> mx) & 0x10;
  677.                     grn = (grn >> mx) & 0x20;
  678.                     blu = (blu >> mx) & 0x40;
  679.                     *dest = colortable[mx | red | grn | blu];
  680.                 }
  681.             }
  682.         }
  683.     }
  684. }
  685.  
  686. #endif
  687.